package com.itheima.reggie.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.reggie.common.Constant;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.common.JwtUtil;
import com.itheima.reggie.common.SmsTemplate;
import com.itheima.reggie.domain.User;
import com.itheima.reggie.mapper.UserMapper;
import com.itheima.reggie.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.util.Map;


@Slf4j
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    //验证码发送业务
    @Override
    public void sendMsg(String phone) {
        // 1.生成6位随机数
        String code = RandomUtil.randomString(6);  // RandomUtil.randomString(位数) 工具类方法
        code="123"; // todo 产品上线之前，需要实现真实短信发送      todo：是高级注释，可以快速定位被注释的代码位置

        // 2.发送短信
        // smsTemplate.sendSms(phone,code);
        log.info("发送短信成功：{}",code);

        // 3.redis存储一份验证码，有效期5分钟
        // 调用Constant类的USER_CODE ="code:拼接前端传过来的phone手机号和生成的随机数验证码，加上验证码存货时间
        //RedisTemplate的opsForValue()方法将手机号为K值，随机生成的验证码为VZ值，加上有效期时间值，存入redis
        redisTemplate.opsForValue().set(Constant.USER_CODE+phone,code, Duration.ofSeconds(300));
                                              // Duration.ofSeconds()工具类方法，ofSeconds是秒值，还有毫秒和分钟等等方法
    }

    // 登录注册
    @Override
    public String login(String phone, String code) {
        // 1.校验验证码
        // 1-1 取出redis中验证码     上面的操作把成功的手机号，验证码都存到redis里了，这里通过opsForValue().get(K值)取出
        String codeRedis = (String) redisTemplate.opsForValue().get(Constant.USER_CODE + phone);
        // 1-2 比较
        if (!StrUtil.equals(code,codeRedis)) { //  比较不一致
            throw new CustomException("验证码不正确"); //验证码不同返回报错，登录不成功
        }

        // 2. 验证码正确到这里，根据phone查询数据库  select * from user where phone = ?
        LambdaQueryWrapper<User> qw = new LambdaQueryWrapper<>();
        qw.eq(User::getPhone,phone);
        User user = userMapper.selectOne(qw);

        // 3.没查到，创建新用户  这里接着上面把查询的结果用User对象存
        if (user == null) {      // 查对象为空
            user = new User();   //这里就是 User user = new User();
            user.setPhone(phone); //  把手机号存入User对象
            user.setStatus(1); // 传个 1 表示正常
            // 保存数据库
            userMapper.insert(user);
        }

        // 4.这里就是完成登录了，然后就是制作token令牌
        // BeanUtil.beanToMap()工具类，自动生成Map，K就是user的所有属性
        Map<String, Object> map = BeanUtil.beanToMap(user);
        String token = JwtUtil.createToken(map);

        // 5.delete(K)，删除redis验证码
        redisTemplate.delete(Constant.USER_CODE + phone);

        // 6.返回token
        return token;
    }
}